
`include "common_header.verilog"

//  *************************************************************************
//  File : pause_rcv_ctl
//  *************************************************************************
//  This program is controlled by a written license agreement.
//  Unauthorized Reproduction or Use is Expressly Prohibited. 
//  Copyright (c) 2009 MoreThanIP.com, Germany
//  Designed by : Daniel Koehler
//  info@morethanip.com
//  *************************************************************************
//               Ethernet MAC Core 
//  *************************************************************************
//  Description: Combined counter for Link Pause and PFC class 0 pause timer.
//               Implement the pause timer to stop the transmitter when a pause
//               frame has been received.
//  Version    : $Id: pause_pfc0_rcv_ctl.v,v 1.2 2010/10/08 14:59:20 dp Exp $
//  *************************************************************************
module pause_pfc0_rcv_ctl (
   
   reset_rxclk,
   xgmii_rxclk,
   xgmii_rxclk_ena,
   pfc_mode_r,
   qtime_r,
   pause_quant_val,
   pause_quant_avb,
   pause_on,
   reset_txclk,
   xgmii_txclk,
   xgmii_txclk_ena,
   pause_wait_t,
   pause_cnt_dec_t);

input   reset_rxclk;            //  Active High reset for xgmii_rxclk domain
input   xgmii_rxclk;            //  XGMII receive clock      
input   xgmii_rxclk_ena;        //  XGMII receive Clock enable
input   pfc_mode_r;             //  PFC mode(1) or Link Pause mode (0) (rxclk)
input   qtime_r;                //  pulse when pause time of 1 expired (512 bits) (rxclk)
input   [15:0] pause_quant_val; //  Pause Quanta value from rx path
input   pause_quant_avb;        //  Pause Quanta value available from rx path
output   pause_on;              //  pause counter is running currently (rxclk)
input   reset_txclk;            //  Active High reset for xgmii_txclk domain
input   xgmii_txclk;            //  XGMII transmit clock      
input   xgmii_txclk_ena;        //  XGMII Transmit Clock enable.
output   pause_wait_t;          //  indicate tx should pause (txclk)
input   pause_cnt_dec_t;        //  MAC tx statemachine is paused, pause counter may decrement now (txclk)
wire    pause_on; 
wire    pause_wait_t; 
wire    pause_cnt_dec;          //  from TX is in idle following a pause request
reg     dec_ok;                 //  pause timer is allowed to dec, TX is in idle
wire    twait;                  //  timer reached zero
reg     pause_wait;             //  tx should stop transmitting

//  get TX signals into rx domain
//  -----------------------------
mtip_xsync #(1) U_S (
          .data_in(pause_cnt_dec_t),
          .reset(reset_rxclk),
          .clk(xgmii_rxclk),
          .data_s(pause_cnt_dec));

always @(posedge reset_rxclk or posedge xgmii_rxclk)
   begin : process_1
   if (reset_rxclk == 1'b 1)
      begin
      dec_ok <= 1'b 0;	//  TX is idle, allow pause decrementing
      pause_wait <= 1'b 0;	
      end
   else
      begin
        //  CLOCK ENABLE 
      if (xgmii_rxclk_ena == 1'b 1)
         begin

        //  allow counter decrement in Link pause mode only when TX is stopped,
        //  always decrement when in PFC mode.
        //  --------------------------------------------------------
         if (pfc_mode_r == 1'b 1 | pfc_mode_r == 1'b 0 & pause_cnt_dec == 1'b 1)
            begin
            dec_ok <= 1'b 1;	
            end
         else
            begin
            dec_ok <= 1'b 0;	
            end

        //  stop TX if link pause is Active
        //  -------------------------------
         if (pfc_mode_r == 1'b 0 & twait == 1'b 1)
            begin
            pause_wait <= 1'b 1;	
            end
         else
            begin
            pause_wait <= 1'b 0;	
            end
         end
      end
   end

//  pause counter
//  -------------
pause_tmr U_T (
          .reset(reset_rxclk),
          .clk(xgmii_rxclk),
          .clk_ena(1'b 1),
          .qtime(qtime_r),          //  rx clock domain
          .dec_ok(dec_ok),
          .quanta_val(pause_quant_val),
          .tload(pause_quant_avb),
          .twait(twait));
          
assign pause_on = twait; //  pause timer non-zero

//  ----------------------------
//  Controls within Tx clock domain
//  ----------------------------

//  Indicate Link Pause to stop TX
//  ------------------------------
mtip_xsync #(1) U_TD (
          .data_in(pause_wait),
          .reset(reset_txclk),
          .clk(xgmii_txclk),
          .data_s(pause_wait_t));       //  hold TX in idle

endmodule // module pause_pfc0_rcv_ctl

